using System;
using System.Collections;
using System.Runtime.InteropServices;
using ADODB;
using Microsoft.CommerceServer.Interop.Configuration;
using System.Text;

namespace Microsoft.CommerceServer.Catalog.Tools
{
	/// <summary>
	/// This class contains methods to access the site resource and retreive the required properties
	/// </summary>
	internal class SiteResourceHelper
	{
		#region Constants
		/// <summary>
		///		Contains the number of resource properties in the inventory system.
		/// </summary>
		internal const int NumberOfCatalogResourceProperties = 2;

		/// <summary>
		///		Contains the name of the catalog resource.
		/// </summary>
		internal const string ProductCatalogResource = "Product Catalog";

		/// <summary>
		///		Contains the connection string property of the catalog resource.
		/// </summary>
		internal const string ConnectionStringProperty = "connstr_db_catalog";

		/// <summary>
		///		Contains the number of resource properties in the inventory system.
		/// </summary>
		internal const int NumberOfInventoryResourceProperties = 6;

		/// <summary>
		///		Contains the name of the inventory resource.
		/// </summary>
		internal const string InventoryResource = "Inventory";

		/// <summary>
		/// Contains a value indicating that SKU codes of back ordered items are returned.
		/// </summary>
		internal const string DisplayBackOrderableSkus = "f_display_bo_skus";

		/// <summary>
		/// Contains a value indicating that SKU codes of pre ordered items are returned.
		/// </summary>
		internal const string DisplayPreOrderableSkus = "f_display_preordered_skus";

		/// <summary>
		/// Contains a value indicating that SKU codes of out-of-stock items are returned.
		/// </summary>
		internal const string DisplayOutOfStockSkus = "f_display_oos_skus";

		/// <summary>
		/// Contains a value indicating that current in-stock quantity is at the out-of-stock threshold.
		/// </summary>
		internal const string FloorIsStockOutThreshold = "f_floor_is_stockout_threshold";

		/// <summary>
		/// Contains a value indicating that missing SKU codes are ignored.
		/// </summary>
		internal const string IgnoreMissingSkus = "f_ignore_missing_skus";

		/// <summary>
		/// Contains a value indicating stock handling.
		/// </summary>
		internal const string StockHandling = "i_stock_handling";

		/// <summary>
		/// Contains the name of the column holding the inventory condition.
		/// </summary>
		internal const string InventoryCondition = "InventoryCondition";

		/// <summary>
		///		Contains the connection string property of the inventory resource.
		/// </summary>
		internal const string InventoryConnectionStringProperty = "connstr_db_inventory";
		#endregion

		#region Methods
		/// <summary>
		/// Returns a Hashtable containing the resource properties for the catalog and inventory resources.
		/// </summary>
		/// <param name="siteName"> The site name. </param>
		/// <param name="getInventoryResourceProperties"> If true will return the inventory resource properties. </param>
		/// <param name="catalogResourceProperies"> A hashtable containing the catalog resource properties. </param>
		/// <param name="inventoryResourceProperies"> A hastable containing the inventory resource properties.</param>
		internal static void GetResourceProperties(string siteName, bool getInventoryResourceProperties,
			out Hashtable catalogResourceProperies, out Hashtable inventoryResourceProperies)
		{
			// This method uses the SiteConfigReadOnlyFreeThreaded object to read the connection string for
			// the product catalog resource.
			SiteConfigReadOnlyFreeThreaded siteConfig = null;
			try
			{

				siteConfig = new SiteConfigReadOnlyFreeThreaded();
				// Initialize the object with the sitename
				siteConfig.Initialize(siteName);
				// Get the catalog resource properties
				catalogResourceProperies = GetCatalogResourceProperties(siteConfig);

				// If the Inventory resource properties should be obtained
				// Get the inventory resource properties if the site contains the inventory resource
				if (getInventoryResourceProperties)
				{
					inventoryResourceProperies = GetInventoryResourceProperties(siteConfig);
				}
				else
				{
					inventoryResourceProperies = null;
				}
			}
			catch (COMException ce)
			{
				throw new CatalogInitializationException(Errors.CatalogContext_FailedGetConnectionString,ce);
			}
			finally
			{
				// Dispose the Siteconfig object
				if (siteConfig != null)
				{
					siteConfig.Dispose();
				}
			}
		}

		/// <summary>
		/// Returns a Hashtable containing the required catalog resource properties.
		/// </summary>
		/// <param name="siteName"> The sitename. </param>
		/// <returns>A Hashtable containing the catalog resource properties.</returns>
		internal static Hashtable GetCatalogResourceProperties(string siteName)
		{
			// This method uses the SiteConfigReadOnlyFreeThreaded object to read the connection string for
			// the product catalog resource.
			SiteConfigReadOnlyFreeThreaded siteConfig = null;
			try
			{

				siteConfig = new SiteConfigReadOnlyFreeThreaded();
				// Initialize the object with the sitename
				siteConfig.Initialize(siteName);
				// Get the catalog resource properties
				return GetCatalogResourceProperties(siteConfig);
			}
			catch (COMException ce)
			{
				throw new CatalogInitializationException(Errors.CatalogContext_FailedGetConnectionString,ce);
			}
			finally
			{
				// Dispose the Siteconfig object
				if (siteConfig != null)
				{
					siteConfig.Dispose();
				}
			}
		}

		/// <summary>
		/// Returns a HashTable containing the catalog resource properties.
		/// </summary>
		/// <param name="siteConfig"> A SiteConfigReadOnlyFreeThreaded initialized with the sitename. </param>
		/// <returns></returns>
		internal static Hashtable GetCatalogResourceProperties(SiteConfigReadOnlyFreeThreaded siteConfig)
		{
			// Create the hastable containing the two catalog resource properties 
			// Connection string and NumberOfFulltextCatalogs to create are the two resource properties
			Hashtable catalogResourceProperties = new Hashtable(NumberOfCatalogResourceProperties);
			_Recordset catalogFields = null;
			try
			{
				// Get the catalog fields collection which is a recordset.
				catalogFields = (_Recordset)siteConfig.Fields[ProductCatalogResource].Value;
				// Add the catalog resource properties that are required to the hashtable and return the hash table
				catalogResourceProperties.Add(ConnectionStringProperty, catalogFields.Fields[ConnectionStringProperty].Value);
				return catalogResourceProperties;
			}
			catch (COMException ce)
			{
				throw new CatalogInitializationException(Errors.CatalogContext_FailedGetConnectionString, ce);
			}
			finally
			{
				// Release the com object
				if (catalogFields != null)
				{
					Marshal.ReleaseComObject(catalogFields);
				}
			}
		}

		/// <summary>
		/// Returns a Hashtable containing the inventory resource properties.
		/// </summary>
		/// <param name="siteName"> The sitename. </param>
		/// <returns>A Hashtable containing the catalog resource properties.</returns>
		internal static Hashtable GetInventoryResourceProperties(string siteName)
		{
			// This method uses the SiteConfigReadOnlyFreeThreaded object to read the connection string for
			// the product catalog resource.
			SiteConfigReadOnlyFreeThreaded siteConfig = null;
			try
			{

				siteConfig = new SiteConfigReadOnlyFreeThreaded();
				// Initialize the object with the sitename
				siteConfig.Initialize(siteName);
				// Get the catalog resource properties
				return GetInventoryResourceProperties(siteConfig);
			}
			catch (COMException ce)
			{
				throw new CatalogInitializationException(Errors.CatalogContext_FailedGetConnectionString, ce);
			}
			finally
			{
				// Dispose the Siteconfig object
				if (siteConfig != null)
				{
					siteConfig.Dispose();
				}
			}
		}

		/// <summary>
		/// Returns a HashTable containing the inventory resource properties.
		/// </summary>
		/// <param name="siteConfig"> A SiteConfigReadOnlyFreeThreaded initialized with the sitename. </param>
		/// <returns></returns>
		internal static Hashtable GetInventoryResourceProperties(SiteConfigReadOnlyFreeThreaded siteConfig)
		{
			// Create the hastable containing the two catalog resource properties 
			// Connection string and NumberOfFulltextCatalogs to create are the two resource properties
			Hashtable inventoryResourceProperties = new Hashtable(NumberOfInventoryResourceProperties);
			_Recordset inventoryFields = null;
			try
			{
				// Get the catalog fields collection which is a recordset.
				inventoryFields = (_Recordset)siteConfig.Fields[InventoryResource].Value;

			}
			catch (COMException)
			{
				// If the Inventory resource does not exist return null
				return null;
			}
			// If the inventory resource exists then add the resource properties
			// to the hash table
			try
			{
				// Add the inventory resource properties to the hashtable and return the hash table
				inventoryResourceProperties.Add(InventoryConnectionStringProperty, inventoryFields.Fields[InventoryConnectionStringProperty].Value);
				inventoryResourceProperties.Add(DisplayBackOrderableSkus, inventoryFields.Fields[DisplayBackOrderableSkus].Value);
				inventoryResourceProperties.Add(DisplayOutOfStockSkus, inventoryFields.Fields[DisplayOutOfStockSkus].Value);
				inventoryResourceProperties.Add(FloorIsStockOutThreshold, inventoryFields.Fields[FloorIsStockOutThreshold].Value);
				inventoryResourceProperties.Add(IgnoreMissingSkus, inventoryFields.Fields[IgnoreMissingSkus].Value);
				inventoryResourceProperties.Add(StockHandling, inventoryFields.Fields[StockHandling].Value);
				inventoryResourceProperties.Add(DisplayPreOrderableSkus, inventoryFields.Fields[DisplayPreOrderableSkus].Value);
				return inventoryResourceProperties;
			}
			catch (COMException ce)
			{
				throw new CatalogInitializationException(Errors.CatalogContext_FailedGetConnectionString, ce);
			}
			finally
			{
				// Release the com object
				if (inventoryFields != null)
				{
					Marshal.ReleaseComObject(inventoryFields);
				}

			}
		}
		#endregion

	}
}
